package com.lu.study.lu.mybatis.plus.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.lu.study.lu.mybatis.plus.service.PlusGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @autor 10758
 * @system lu-pro-arch
 * @Time 2018/12/6
 */
@Service
@Slf4j
public class PlusGeneratorImpl implements PlusGenerator {
    @Value("${modelName}")
    private String modelName;
    @Value("${packageName}")
    private String packageName;
    @Value("${tableNames}")
    private String tableNames;
    @Value("${excludedFields}")
    private String excludedFields;
    @Value("${outputDir}")
    private String outputDir;
    @Value("${spring.datasource.url}")
    private String dbUrl;
    @Value("${spring.datasource.username}")
    private String userName;
    @Value("${spring.datasource.password}")
    private String pwd;

    @Override
    public void generator() {
        String baseDir = System.getProperty("user.dir");
        log.info(baseDir);

        // 配置数据源
        DataSourceConfig.Builder dataSourceConfig = new DataSourceConfig
                .Builder(dbUrl, userName, pwd);
        String user = System.getProperty("user.name");
        // 快速自动生成代码器
        FastAutoGenerator generator = FastAutoGenerator.create(dataSourceConfig);
        // 全局配置
        generator.globalConfig(globalConfig(user));
        // 包配置
        generator.packageConfig(getPageConfig());
        // 策略配置
        generator.strategyConfig(strateConfig());
        // 3.2 自定义路径，多种情况自行添加 pathInfo.put
        Map<OutputFile, String> pathInfo = new HashMap<>();
        // 单独配置xml路径，可覆盖全局配置。
        pathInfo.put(OutputFile.mapperXml, outputDir + "//resources//mapper");
        generator.packageConfig((builder) -> builder.pathInfo(pathInfo));
        // 4 自定义模板配置，配置模板路径
        generator.templateConfig(templateConfig());
        // 7 设置自定义模板
        generator.injectionConfig(extConfig());
        // 自定义模板类型
        generator.templateEngine(new LuCustomVelocityTemplateEngine());
        // 8 执行
        generator.execute();
    }

    private Consumer<InjectionConfig.Builder> extConfig() {
        Map<String, Object> extMap = new HashMap<>(16);
        extMap.put("modelName", modelName);
        return builder -> builder
                .customMap(extMap)
                .beforeOutputFile((tableInfo, objectMap) -> {
                    extMap.put("modelName", modelName);
                    extMap.put("under_line_entity_name", StrUtil.toUnderlineCase(tableInfo.getName()));
                    extMap.put("dtoName", StrUtil.upperFirst(tableInfo.getName()));
                    System.out.println("------------------tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
                    builder.customMap(extMap);
                })
                .customFile(Collections.singletonMap("Dto.java", "/template/vm/dto.java.vm"))
                ;
    }

    private Consumer<StrategyConfig.Builder> strateConfig() {
        return (builder) -> builder.entityBuilder().formatFileName("%sEntity")
                // 基于数据库字段，忽略某个字段，【好像不管用】
                // .addSuperEntityColumns("id", "create_by", "create_time", "update_by", "update_time", "delete_flag")
                .mapperBuilder().formatMapperFileName("%sMapper").formatXmlFileName("%sMapper")
                .serviceBuilder().formatServiceFileName("%sService")
                .controllerBuilder().formatFileName("%sController");
    }

    private Consumer<TemplateConfig.Builder> templateConfig() {
        return builder -> builder
                // 禁用模板	TemplateType.ENTITY
                .disable(TemplateType.ENTITY)
                // 设置实体模板路径(JAVA)	/templates/entity.java
                .entity("/template/vm/entity.java")
                .service("/template/vm/service.java")
                .serviceImpl("/template/vm/serviceImpl.java")
                .mapper("/template/vm/mapper.java")
                .mapperXml("/template/vm/mapper.xml")
                .controller("/template/vm/controller.java")
                .build();
    }

    private Consumer<PackageConfig.Builder> getPageConfig() {
        return (builder) ->
                builder.parent(packageName)
                        // 父包模块名	默认值:无
                        .moduleName(modelName)
                        // Entity 包名	默认值:entity
                        .entity("domain.entity")
                        // Service 包名	默认值:service
                        .service("service")
                        // Service Impl 包名	默认值:service.impl
                        .serviceImpl("service.impl")
                        // Mapper 包名	默认值:mapper
                        .mapper("mapper")
                        // Mapper XML 包名	默认值:mapper.xml
                        .xml("mapper.xml")
                        // Controller 包名	默认值:controller
                        .controller("controller")
                        // 自定义文件包名	输出自定义文件时所用到的包名
                        .other("");
    }

    private Consumer<GlobalConfig.Builder> globalConfig(String user) {
        return (builder) -> builder
                // 覆盖已生成文件
                .fileOverride()
                // 禁止打开输出目录	默认值:true
                .disableOpenDir()
                .outputDir(outputDir + "//java")
                .author(user)
                .enableSwagger();
    }

}
